home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUT03NEW.ZIP / TUT3.CPP < prev    next >
C/C++ Source or Header  |  1994-12-07  |  16KB  |  433 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //                                                                         //
  3. // TUTPROG3.CPP - VGA Trainer Program 3 (in Turbo C++ 3.0)                 //
  4. //                                                                         //
  5. // "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
  6. // was limited to Pascal only in its first run.  All I have done is taken  //
  7. // his original release, translated it to C++ and touched up a few things. //
  8. // I take absolutely no credit for the concepts presented in this code and //
  9. // am NOT the person to ask for help if you are having trouble.            //
  10. //                                                                         //
  11. // Program Notes : This program presents many new concepts, including:     //
  12. //                 Cirle and Line algorithms.                              //
  13. //                                                                         //
  14. //                 If you are compiling this code command line, be sure to //
  15. //                 use the "-ml" parameter (large memory model).           //
  16. //                 Otherwise, the program will compile and link, but will  //
  17. //                 lock up your system.                                    //
  18. //                                                                         //
  19. // Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
  20. // Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
  21. //                                                                         //
  22. // Last Modified : December 7, 1994                                        //
  23. //                                                                         //
  24. /////////////////////////////////////////////////////////////////////////////
  25.  
  26. //               //
  27. // INCLUDE FILES //
  28. //               //
  29.  
  30.   #include <conio.h>
  31.               // getch(), clrscr(), kbhit()
  32.   #include <dos.h>
  33.               // MK_FP, Geninterrupt()
  34.   #include <math.h>
  35.               // floor(), ceil(), abs(), sin(), cos()
  36.   #include <iostream.h>
  37.               // cout, endl, memset(), _fmemset()
  38.  
  39. //                     //
  40. // FUNCTION PROTOTYPES //
  41. //                     //
  42.  
  43.   // MODE SETTING FUNCTIONS
  44.   void SetMCGA();
  45.   void SetText();
  46.  
  47.   // PALLETTE FUNCTIONS
  48.   void Pal    (unsigned char ColorNo,  unsigned char R,
  49.            unsigned char G,        unsigned char B);
  50.   void PalPlay();
  51.  
  52.   // SMALL UTILITY FUNCTIONS
  53.   int  sgn    (long a);
  54.   int  round  (long a);
  55.  
  56.   // DRAWING FUNCTIONS
  57.   void Putpixel (int  x, int  y, unsigned char Col);
  58.   void Line     (int  a, int  b, int   c, int  d, int col);
  59.   void Line2    (int x1, int y1, int  x2, int y2, int col);
  60.   void Circle   (int  X, int  Y, int rad, int col);
  61.   void WaitRetrace();
  62.  
  63. //                              //
  64. // GLOBAL VARIABLE DECLARATIONS //
  65. //                              //
  66.  
  67.   // declare a pointer to the offset of VGA memory
  68.   unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
  69.  
  70.   // This declares the PALL variable. 0 to 255 signifies the colors of the
  71.   // pallette, 1 to 3 signifies the Red, Green and Blue values. I am
  72.   // going to use this as a sort of "virtual pallette", and alter it
  73.   // as much as I want, then suddenly bang it to screen. Pall2 is used
  74.   // to "remember" the origional pallette so that we can restore it at
  75.   // the end of the program. */
  76.   unsigned char Pall[256][3], Pall2[256][3];
  77.  
  78. ///////////////////////////////////////////////////////////////////////////////
  79. //                                                                           //
  80. //                                MAIN FUNCTION                              //
  81. //                                                                           //
  82. ///////////////////////////////////////////////////////////////////////////////
  83.  
  84. void main() {
  85.  
  86.   clrscr();
  87.   cout
  88.     << "This sample program will test out our line and circle algorithms.\n"
  89.     << "In the first part, many circles will be draw creating (hopefully)\n"
  90.     << "a ""tunnel"" effect. I will the rotate the pallete to make it look\n"
  91.     << "nice. I will then draw some lines and rotate the pallette on them\n"
  92.     << "too. Note : I am using the slower (first) line algorithm (in\n"
  93.     << "procedure line2). Change it to Procedure Line and it will be using\n"
  94.     << "the second line routine. NB : For descriptions on how pallette works\n"
  95.     << "have a look at part two of this series; I won''t re-explain it here."
  96.     << endl << endl;
  97.   cout
  98.     << "Remember to send me any work you have done, I am most eager to help."
  99.     << endl << endl;
  100.   cout
  101.     << "Hit any key to continue ...";
  102.   getch();
  103.   SetMCGA();
  104.  
  105.   // This sets colors 1 to 199 to values between 33 to 63. The MOD
  106.   // function gives you the remainder of a division, ie. 105 mod 10 = 5 }
  107.   for (int loop1=1; loop1<200; loop1++) {
  108.     Pall[loop1][0] = (loop1 % 30) + 33;
  109.     Pall[loop1][1] = 0;
  110.     Pall[loop1][2] = 0;
  111.   }
  112.  
  113.   WaitRetrace();
  114.  
  115.   // This sets the true pallette to variable Pall
  116.   for (loop1=1; loop1<200; loop1++)
  117.     Pal(loop1, Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
  118.  
  119.   // This draws 90 circles all with centers at 160,100 with increasing
  120.   // radii and colors.
  121.   for (loop1=1; loop1<91; loop1++)
  122.     Circle(160, 100, loop1, loop1);
  123.  
  124.   // wait until a key is pressed
  125.   while (!kbhit()) PalPlay();
  126.   // make sure to clear the keyboard buffer
  127.   getch();
  128.  
  129.   // This draws 199 lines, all starting at 0,1
  130.   for (loop1=1; loop1<200; loop1++)
  131.     Line2 (0,1,319,loop1,loop1);   // *** Replace Line2 with Line to use the
  132.                    // second line algorithm ***
  133.  
  134.   while (!kbhit()) PalPlay();
  135.   getch();
  136.  
  137.   getch();
  138.  
  139.   SetText();
  140.  
  141.   cout
  142.     << "All done. Okay, so maybe it wasn''t a tunnel effect, but you get the\n"
  143.     << "general idea ;-) This concludes the third sample program in the ASPHYXIA\n"
  144.     << "Training series. You may reach DENTHOR under the name of GRANT SMITH\n"
  145.     << "on the MailBox BBS, or leave a message to ASPHYXIA on the ASPHYXIA BBS\n"
  146.     << "Get the numbers from Roblist, or write to :\n"
  147.     << "             Grant Smith\n"
  148.     << "             P.O. Box 270\n"
  149.     << "             Kloof\n"
  150.     << "             3640\n" << endl;
  151.   cout << "I hope to hear from you soon!" << endl << endl;
  152.   cout << "Hit any key to exit ...";
  153.  
  154.   getch();
  155. }
  156.  
  157.  
  158. /////////////////////////////////////////////////////////////////////////////
  159. //                                                                         //
  160. // SetMCGA() - This function gets you into 320x200x256 mode.               //
  161. //                                                                         //
  162. /////////////////////////////////////////////////////////////////////////////
  163.  
  164. void SetMCGA() {
  165.   _AX = 0x0013;
  166.   geninterrupt (0x10);
  167. }
  168.  
  169.  
  170. /////////////////////////////////////////////////////////////////////////////
  171. //                                                                         //
  172. // SetText() - This function gets you into text mode.                      //
  173. //                                                                         //
  174. /////////////////////////////////////////////////////////////////////////////
  175.  
  176. void SetText() {
  177.   _AX = 0x0003;
  178.   geninterrupt (0x10);
  179. }
  180.  
  181.  
  182. /////////////////////////////////////////////////////////////////////////////
  183. //                                                                         //
  184. // Pal() - This sets the Red, Green, and Blue values of a certain color.   //
  185. //                                                                         //
  186. /////////////////////////////////////////////////////////////////////////////
  187.  
  188. void Pal(unsigned char ColorNo, unsigned char R,
  189.      unsigned char G,       unsigned char B) {
  190.  
  191.   outp (0x03C8,ColorNo); // here is the pallette color I want to set
  192.   outp (0x03C9,R);
  193.   outp (0x03C9,G);
  194.   outp (0x03C9,B);
  195.  
  196. }
  197.  
  198.  
  199. /////////////////////////////////////////////////////////////////////////////
  200. //                                                                         //
  201. // PalPlay() - This function mucks about with our "virtual pallette", then //
  202. //             shoves it to the screen.                                    //
  203. //                                                                         //
  204. /////////////////////////////////////////////////////////////////////////////
  205.  
  206. void PalPlay() {
  207.  
  208. unsigned char Tmp[3];
  209.  
  210.   // This copies color 199 from our virtual pallette to the Tmp variable.
  211.   _fmemmove(Tmp,Pall[199],3);
  212.  
  213.   // This moves the entire virtual pallette up one color.
  214.   _fmemmove(Pall[2],Pall[1],199*3);
  215.  
  216.   // This copies the Tmp variable to the bottom of the virtual pallette.
  217.   // Don't change 0: leave this always black to not change overscan color.
  218.   _fmemmove(Pall[1],Tmp,3);
  219.  
  220.   WaitRetrace();
  221.   for (int loop1=0;loop1<256;loop1++)
  222.    Pal(loop1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
  223.  
  224. }
  225.  
  226.  
  227. /////////////////////////////////////////////////////////////////////////////
  228. //                                                                         //
  229. // sgn() - This function is used by Line() to determine the sign of a long //
  230. //                                                                         //
  231. /////////////////////////////////////////////////////////////////////////////
  232.  
  233. int sgn (long a) {
  234.   if (a > 0) return +1;
  235.   else if (a < 0) return -1;
  236.   else return 0;
  237.  
  238. }
  239.  
  240.  
  241. /////////////////////////////////////////////////////////////////////////////
  242. //                                                                         //
  243. // round() - This function is used by Line() to round a long to the        //
  244. //           nearest integer.                                              //
  245. //                                                                         //
  246. /////////////////////////////////////////////////////////////////////////////
  247.  
  248. int round (long a) {
  249.   if ( (a - (int)a) < 0.5) return floor(a);
  250.     else return ceil(a);
  251. }
  252.  
  253.  
  254. /////////////////////////////////////////////////////////////////////////////
  255. //                                                                         //
  256. // Putpixel() - This puts a pixel on the screen by writing directly to     //
  257. //              memory.                                                    //
  258. //                                                                         //
  259. /////////////////////////////////////////////////////////////////////////////
  260.  
  261. void Putpixel (int x, int y, unsigned char Col) {
  262.   memset(vga+(x+(y*320)),Col,1);
  263. }
  264.  
  265.  
  266. /////////////////////////////////////////////////////////////////////////////
  267. //                                                                         //
  268. // Line() - This draws a line from a,b to c,d of color col.                //
  269. //          This function will be explained in more detail in tut3new.zip  //
  270. //                                                                         //
  271. /////////////////////////////////////////////////////////////////////////////
  272.  
  273. void Line(int a, int b, int c, int d, int col) {
  274.  
  275.   long u,s,v,d1x,d1y,d2x,d2y,m,n;
  276.   int  i;
  277.  
  278.   u   = c-a;      // x2-x1
  279.   v   = d-b;      // y2-y1
  280.   d1x = sgn(u);   // d1x is the sign of u (x2-x1) (VALUE -1,0,1)
  281.   d1y = sgn(v);   // d1y is the sign of v (y2-y1) (VALUE -1,0,1)
  282.   d2x = sgn(u);   // d2x is the sign of u (x2-x1) (VALUE -1,0,1)
  283.   d2y = 0;
  284.   m   = abs(u);   // m is the distance between x1 and x2
  285.   n   = abs(v);   // n is the distance between y1 and y2
  286.  
  287.   if (m<=n) {     // if the x distance is greater than the y distance
  288.     d2x = 0;
  289.     d2y = sgn(v); // d2y is the sign of v (x2-x1) (VALUE -1,0,1)
  290.     m   = abs(v); // m is the distance between y1 and y2
  291.     n   = abs(u); // n is the distance between x1 and x2
  292.   }
  293.  
  294.   s = (int)(m / 2); // s is the m distance (either x or y) divided by 2
  295.  
  296.   for (i=0;i<round(m);i++) { // repeat this loop until it
  297.                  // is = to m (y or x distance)
  298.     Putpixel(a,b,col);       // plot a pixel at the original x1, y1
  299.     s += n;                  // add n (dis of x or y) to s (dis of x of y)
  300.     if (s >= m) {            // if s is >= m (distance between y1 and y2)
  301.       s -= m;
  302.       a += d1x;
  303.       b += d1y;
  304.     }
  305.     else {
  306.       a += d2x;
  307.       b += d2y;
  308.     }
  309.   }
  310.  
  311. }
  312.  
  313.  
  314. /////////////////////////////////////////////////////////////////////////////
  315. //                                                                         //
  316. // Line2() - This function draws a line from x1,y1 to x2,y2 using the      //
  317. //           first method.                                                 //
  318. //                                                                         //
  319. /////////////////////////////////////////////////////////////////////////////
  320.  
  321. void Line2(int x1, int y1, int x2, int y2, int col) {
  322.  
  323.   int   x, y, xlength, ylength, dx, dy;
  324.   float xslope, yslope;
  325.  
  326.   xlength = abs(x1-x2);
  327.   if ((x1-x2)  < 0) dx = -1;
  328.   if ((x1-x2) == 0) dx =  0;
  329.   if ((x1-x2)  > 0) dx = +1;
  330.  
  331.   ylength = abs(y1-y2);
  332.   if ((y1-y2)  < 0) dy = -1;
  333.   if ((y1-y2) == 0) dy =  0;
  334.   if ((y1-y2)  > 0) dy = +1;
  335.  
  336.   if (dy == 0) {
  337.     if (dx < 0)
  338.       for (x=x1; x<x2+1; x++)
  339.     Putpixel (x,y1,col);
  340.     if (dx > 0)
  341.       for (x=x2; x<x1+1; x++)
  342.     Putpixel (x,y1,col);
  343.   }
  344.  
  345.   if (dx == 0) {
  346.     if (dy < 0)
  347.       for (y=y1; y<y2+1; y++)
  348.     Putpixel (x1,y,col);
  349.     if (dy > 0)
  350.       for (y=y2; y<y1+1; y++)
  351.     Putpixel (x1,y,col);
  352.   }
  353.  
  354.   if ((xlength != 0) && (ylength != 0)) {
  355.     xslope = (float)xlength/(float)ylength;
  356.     yslope = (float)ylength/(float)xlength;
  357.   }
  358.   else {
  359.     xslope = 0.0;
  360.     yslope = 0.0;
  361.   }
  362.  
  363.   if ((xslope != 0) && (yslope != 0) &&
  364.       (yslope/xslope < 1) && (yslope/xslope > -1)) {
  365.     if (dx < 0)
  366.       for (x=x1; x<x2+1; x++) {
  367.     y = round (yslope*x);
  368.     Putpixel (x,y,col);
  369.       }
  370.     if (dx > 0)
  371.       for (x=x2; x<x1+1; x++) {
  372.     y = round (yslope*x);
  373.     Putpixel (x,y,col);
  374.       }
  375.   }
  376.   else {
  377.     if (dy < 0)
  378.       for (y=x1; y<x2+1; y++) {
  379.     x = round (xslope*y);
  380.     Putpixel (x,y,col);
  381.       }
  382.     if (dy > 0)
  383.       for (y=x2; y<x1+1; y++) {
  384.     x = round (xslope*y);
  385.     Putpixel (x,y,col);
  386.       }
  387.   }
  388.  
  389. }
  390.  
  391. /////////////////////////////////////////////////////////////////////////////
  392. //                                                                         //
  393. // Circle() - This draws a circle with center X,Y, with Rad as its radius. //
  394. //                                                                         //
  395. /////////////////////////////////////////////////////////////////////////////
  396.  
  397. void Circle(int X, int Y, int rad, int col) {
  398.  
  399.   float deg = 0;
  400.  
  401.   do {
  402.     X = round(rad * cos(deg));
  403.     Y = round(rad * sin(deg));
  404.     Putpixel (X+160, Y+100, col);
  405.     deg += 0.005;
  406.   }
  407.   while (deg <= 6.4);
  408.  
  409. }
  410.  
  411. /////////////////////////////////////////////////////////////////////////////
  412. //                                                                         //
  413. // WaitRetrace() - This waits until you are in a Verticle Retrace.         //
  414. //                                                                         //
  415. /////////////////////////////////////////////////////////////////////////////
  416.  
  417. void WaitRetrace() {
  418.  
  419.   _DX = 0x03DA;
  420.  
  421.   l1: asm {
  422.     in  al,dx;
  423.     and al,0x08;
  424.     jnz l1;
  425.       }
  426.  
  427.   l2: asm {
  428.     in  al,dx;
  429.     and al,0x08;
  430.     jz  l2;
  431.       }
  432. }
  433.